<?php
/**
 * <https://y.st./>
 * Copyright © 2017 Alex Yst <mailto:copyright@y.st>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org./licenses/>.
**/

$xhtml = array(
	'<{title}>' => 'Unit5.java',
	'<{subtitle}>' => 'Written in <span title="Programming 2">CS 1103</span> of <a href="http://www.uopeople.edu/">University of the People</a>, finalised on 2017-07-19',
	'<{copyright year}>' => '2017',
	'takedown' => '2017-11-01',
	'<{body}>' => <<<END
<h2>Source code</h2>
<blockquote>
<pre><code>/* 
 * Copyright (C) 2017 Alex Yst
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 */
package st.y.CS1103.Unit5;

/**
 * Alex Yst&apos;s CS 1103 (Programming 2) Unit 5 submission
 * 
 * This program loads a dictionary file, then processes a second file and
 * checks it for misspellings.
 * 
 * @author Alex Yst
 */
public class Unit5 {
/**
 * The main method reads the dictionary file (which must be present in the
 * Eclipse project repository), then asks the user for a file. The user&apos;s file
 * is checked for spelling errors and a list of suggested spellings is output.
 * 
 * @param arguments Command line arguments are ignored.
 */
	public static void main(String[] arguments) {
		try {
			java.util.Scanner filein = new java.util.Scanner(new java.io.File(&quot;words.txt&quot;));
			java.util.HashSet&lt;String&gt; dict = new java.util.HashSet&lt;String&gt;();
			while (filein.hasNext()) {
				dict.add(filein.next().toLowerCase());
			}
			filein.close();
			System.out.print(&quot;Words included in the dictionary (should be 72875): &quot;);
			System.out.println(dict.size());
			filein = new java.util.Scanner(getInputFileNameFromUser());
			filein.useDelimiter(&quot;[^a-zA-Z]+&quot;);
			java.util.HashSet&lt;String&gt; misspelled = new java.util.HashSet&lt;String&gt;();
			while (filein.hasNext()) {
				String word = filein.next().toLowerCase();
				if(!dict.contains(word)) {
					if(!misspelled.contains(word)) {
						misspelled.add(word);
						System.out.print(word);
						System.out.print(&quot;: &quot;);
						java.util.TreeSet&lt;String&gt; corrections = corrections(word, dict);
						if(corrections.isEmpty()) {
							System.out.println(&quot;(no suggestions)&quot;);
						} else {
							java.util.Iterator&lt;String&gt; it = corrections.iterator();
							System.out.print(it.next());
							while(it.hasNext()) {
								System.out.print(&quot;, &quot;);
								System.out.print(it.next());
							}
							System.out.println();
						}
					}
				}
			}
			filein.close();
		} catch(java.io.FileNotFoundException e) {
			System.out.println(e.getMessage());
		} catch(NullPointerException e) {
			System.out.println(&quot;File not chosen; aborting.&quot;);
		}
		
	}
/**
 * Lets the user select an input file using a standard file
 * selection dialog box.  If the user cancels the dialog
 * without selecting a file, the return value is null.
 */
	static java.io.File getInputFileNameFromUser() {
		javax.swing.JFileChooser fileDialog = new javax.swing.JFileChooser();
		fileDialog.setDialogTitle(&quot;Select File for Input&quot;);
		int option = fileDialog.showOpenDialog(null);
		if (option != javax.swing.JFileChooser.APPROVE_OPTION) {
			return null;
		} else {
			return fileDialog.getSelectedFile();
		}
	}
/**
 * This method attempts to figure out what correctly-spelled word a misspelled
 * word was meant to be. A set of suggestions, if any can be found, are
 * returned.
 * 
 * @param badWord A word not present in the dictionary
 * @param dictionary The dictionary of valid words
 * @return A set of words the user may have meant to type
 */
	static java.util.TreeSet&lt;String&gt; corrections(String badWord, java.util.HashSet&lt;String&gt; dictionary) {
		java.util.TreeSet&lt;String&gt; set = new java.util.TreeSet&lt;String&gt;();
		for(int i=0;i&lt;badWord.length();i++) {
			String prefix = badWord.substring(0,i);
			String suffix = badWord.substring(i+1);
// Delete any one of the letters from the misspelled word.
			addWord(prefix+suffix, set, dictionary);
			for(char c=&apos;a&apos;;c&lt;=&apos;z&apos;;c++) {// C++? No, I think this is Java.
// Change any letter in the misspelled word to any other letter.
				addWord(prefix+c+suffix, set, dictionary);
			}
		}
		for(int i=0;i&lt;=badWord.length();i++) {
			String prefix = badWord.substring(0,i);
			String suffix = badWord.substring(i);
// Insert a space at any point in the misspelled word (and check that both of
// the words that are produced are in the dictionary)
			addWords(prefix, suffix, set, dictionary);
			for(char c=&apos;a&apos;;c&lt;=&apos;z&apos;;c++) {// C++? No, I think this is Java.
// Insert any letter at any point in the misspelled word.
				addWord(prefix+c+suffix, set, dictionary);
			}
		}
		for(int i=0;i&lt;badWord.length()-1;i++) {
			String prefix = badWord.substring(0,i);
			String letter0 = badWord.substring(i+1, i+2);
			String letter1 = badWord.substring(i, i+1);
			String suffix = badWord.substring(i+2);
// Swap any two neighbouring characters in the misspelled word.
			addWord(prefix+letter0+letter1+suffix, set, dictionary);
		}
		return set;
	}
/**
 * Checks a potential word for validity, then adds it to the list of suggested
 * spellings.
 * 
 * @param word The potential suggestion
 * @param set The set of suggestions found thus far
 * @param dictionary The dictionary of valid words
 */
	static public void addWord(String word, java.util.TreeSet&lt;String&gt; set, java.util.HashSet&lt;String&gt; dictionary) {
		if(dictionary.contains(word)) {
			set.add(word);
		}
	}
/**
 * Checks a pair of words for validity, then adds them to the list of suggested
 * spellings.
 * 
 * @param word0 The first word of the pair
 * @param word1 The second word of the pair
 * @param set The set of suggestions found thus far
 * @param dictionary The dictionary of valid words
 */
	static public void addWords(String word0, String word1, java.util.TreeSet&lt;String&gt; set, java.util.HashSet&lt;String&gt; dictionary) {
		if(dictionary.contains(word0) &amp;&amp; dictionary.contains(word1)) {
			set.add(word0+&apos; &apos;+word1);
		}
	}
}</code></pre>
</blockquote>
<h2>Output (when run on itself)</h2>
<blockquote>
<pre>Words included in the dictionary (should be 72875): 72875
c: a, ac, ca, cd, cf, ci, cl, cm, co, cr, cs, cu, kc, sc, tc
yst: cyst, myst, st, yest, yet
merchantability: merchant ability
http: (no suggestions)
www: wow
org: borg, erg, or, ora, orb, ore, orgy, orr
y: a, ay, by, my, ty, ya, yb, ye, yo
s: a, as, cs, es, gs, is, ks, ls, ms, os, rs, sb, sc, se, sh, si, sm, sn, so, sq, sr, st, ts, us, vs
param: pa ram, par am, pram
util: until
filein: file in
txt: tat, tet, text, tit, tot, tut
hashset: hash set
dict: dice, dick, dicta, diet, dint, dirt, duct, edict, pict
hasnext: has next
tolowercase: to lowercase
println: print ln
getinputfilenamefromuser: (no suggestions)
usedelimiter: use delimiter
za: a, ba, ca, fa, ga, ha, la, ma, na, pa, ra, ta, va, ya, zap, zn, zr
z: a, hz, oz, zn, zr
treeset: tree set
isempty: is empty
filenotfoundexception: (no suggestions)
e: a, be, ed, eh, em, er, es, eu, ex, fe, ge, he, le, me, ne, re, se, we, xe, ye
getmessage: get message
nullpointerexception: (no suggestions)
javax: java, javas
jfilechooser: (no suggestions)
filedialog: file dialog
setdialogtitle: (no suggestions)
int: ant, dint, hint, in, ina, inc, ind, ink, inn, ins, inti, into, it, lint, mint, nit, pint, tint
showopendialog: (no suggestions)
getselectedfile: (no suggestions)
badword: bad word
i: a, bi, ci, di, hi, id, if, in, io, ir, is, it, li, mi, ni, pi, si, ti
substring: sub string
addword: add word
addwords: add words
neighbouring: neighboring</pre>
</blockquote>
<p>
	(It&apos;s worth noting that the word &quot;neighbouring&quot; is spelled correctly in English English (British English), but the dictionary we used for the assignment was in Statesian English, so the word got flagged as misspelled.
	As I actually did spell it right though, I didn&apos;t change the spelling in the comments.)
</p>
END
);
